import wsgiref.util
import cgi
import urlparse
import datetime
import time

import MSConfig; MSConfig.init('.')
import sys; sys.path.append('..' + MSConfig.DIRSEP + 'refact-full')
import MSLogger; log = MSLogger.get('wsgi_server')
import MSDatabase
import MSWSGIPatterns as w
import MSObject
import MSObjects
import MSDatetime
import ReaderMSAPI
import ReaderMSDB

def method_list_objects(environ):
    ret = []
    ret += w.openObjectCommonTable()
    c = 0
    for oid,obj in MSObjects.genObjects(MSConfig.config.get('main','dbpath')):
        ret += w.getObjectCommonInfo(c, obj)
        c += 1
    ret += w.closeObjectCommonTable()
    return ret

def method_get_object(environ):
    form    = cgi.FieldStorage(fp=environ['wsgi.input'], environ=environ)

    if form.getvalue('obj_fromDisk'):
        fromDisk = True
    else:
        fromDisk = False

    name = form.getvalue('obj_name')
    if not w.checkName(name): 
        if not name: name = ''
        log.debug('method_get_object_events: incorrect name %s', name)
        return ['object ' + name + ' not found']
    if fromDisk:
        obj = MSObject.MSObject(MSConfig.config.get('main', 'dbpath'), name)
        obj.open()
    else:
        obj = MSDatabase.getInstance().objs.find(name)
    if (not obj) or  obj.storage.txn == 0:
        log.debug('method_get_object: not found %s', name)
        return ['object ' + name + ' not found']

    ret = []
    ret += w.openObjectCommonTable()
    ret += w.getObjectCommonInfo(1, obj)
    ret += w.closeObjectCommonTable()

    ret += w.getObjectDetailedInfo(obj)

    return ret

def method_destroy_object(environ):
    form    = cgi.FieldStorage(fp=environ['wsgi.input'], environ=environ)
    obj_name = form.getvalue('obj_name')

    obj     = MSObject.MSObject(MSConfig.config.get('main','dbpath'), obj_name)
    obj.open()
    if obj.storage.txn == 0:
        return ['object does not exist']
    obj.storage.destroy()
    return ['success']

def method_create_object(environ):
    form    = cgi.FieldStorage(fp=environ['wsgi.input'], environ=environ)
    name = form.getvalue('obj_name')
    if not w.checkName(name): 
        if not name: name = ''
        log.debug('method_get_object_events: incorrect name %s', name)
        return ['object ' + name + ' not found']
    if len(name) < 4: return ['obj name should be larger']

    obj     = MSObject.MSObject(MSConfig.config.get('main','dbpath'), name)
    obj.open()
    if obj.storage.txn > 0: return ['object already exists']

    obj.storage.meta['msId']    = form.getvalue('obj_msId')
    obj.storage.meta['pcnId']   = form.getvalue('obj_pcnId')
    obj.storage.meta['skey']    = form.getvalue('obj_skey')
    obj.flush()
    return ['success'] 

def method_get_object_events(environ):
    form        = cgi.FieldStorage(fp=environ['wsgi.input'], environ=environ)

    if form.getvalue('obj_tail'):
        tail = True
    else:
        tail = False

    if form.getvalue('obj_useapi'):
        useAPI = True
    else:
        useAPI = False

    if form.getvalue('obj_usedb'):
        useDB  = True
    else:
        useDB  = False

    reader = None
    if useAPI:
        reader = ReaderMSAPI.Reader(MSConfig.config.get('msapi','url'))
    if useDB:
        reader = ReaderMSDB.Reader(MSConfig.config.get('msdb','host'),
                                   MSConfig.config.get('msdb','port'),
                                   MSConfig.config.get('msdb','dbname'),
                                   MSConfig.config.get('msdb','user'),
                                   MSConfig.config.get('msdb','pwd'))

    startdate   = form.getvalue('obj_startdate')
    if startdate == None:
        startdate = MSDatetime.getToday()[0]
    else:
        startdate = datetime.datetime.strptime(startdate, MSDatetime.TIME_FORMAT_MAGICDB_ORIG)

    name        = form.getvalue('obj_name')
    if not w.checkName(name): 
        if not name: name = ''
        log.debug('method_get_object_events: incorrect name %s', name)
        return ['object ' + name + ' not found']
    obj  = MSDatabase.getInstance().objs.find(name)
    if reader != None:
        obj  = MSObject.MSObject(MSConfig.config.get('main', 'dbpath'), name)
        obj.open()
        if obj.storage.txn == 0:
            log.debug('method_get_object_events: not found %s', name)
            return ['object ' + name + ' not found']
        obj.lock.acquire()
        try:
            reader.getEvents_TIMED(obj, startdate)
        finally:
            obj.lock.release()

    ret = []
    ret += ['<h3>']
    ret += ['object "' + str(obj.objId) + '" since ' + startdate.strftime(MSDatetime.TIME_FORMAT_MAGICDB_ORIG)]
    ret += ['</h3><br/>']

    if tail:
        ret += w.openObjectEventTable(False)
    else:
        ret += w.openObjectEventTable(True)

    copied_events = list(obj.events)
    copied_events.reverse()
    for e in copied_events:
        ret += w.getObjectEventCommonInfo(e)
    ret += w.closeObjectEventTable()

    ret += ['<div class="eventTableSize">%d</div>' % len(obj.events)]
    ret += ['events processed totally at:']
    ret += ['<div class="eventTableUpdTime">' + (datetime.datetime.fromtimestamp(time.time())).strftime(MSDatetime.TIME_FORMAT_MAGICDB_ORIG) + '</div><br>']
    if tail:
        ret += ['<div class="eventTableObjName" hidden="true">' + name + '</div>']
        ret += ['<div class="eventTablePlaceholder" hidden="true"></div>']
        ret += ['<div class="eventTableAutoUpdate" hidden="true">true</div>']
        ret += ['<a class="maya2" href="blank">Enable RealTime Monitoring</a><br>']
    if useAPI:
        ret += ['<div class="eventTableMethod" hidden="true">api</div>']
    elif useDB:
        ret += ['<div class="eventTableMethod" hidden="true">db</div>']
    else:
        ret += ['<div class="eventTableMethod" hidden="true"></div>']
    return ret

def handle_method(environ, start_response):
    w.putHeader(start_response, 200, 'html')
    mname = wsgiref.util.shift_path_info(environ)
    if mname == 'create_object':
        return method_create_object(environ)
    if mname == 'get_object_events':
        return method_get_object_events(environ)
    if mname == 'destroy_object':
        return method_destroy_object(environ)
    if mname == 'list_objects':
        return method_list_objects(environ)
    if mname == 'get_object':
        return method_get_object(environ)
    return ['not_found']
